// dllmain.cpp: definisce il punto di ingresso per l'applicazione DLL.
#include "stdafx.h"

#define MOUSEDLL_LIBAPI extern "C" __declspec(dllexport)
#include "MouseDLL.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

BOOL connected(){
	BOOL err = false;
	GUID id;

	//The HidD_GetHidGuid routine returns the device interfaceGUID for HIDClass devices
	HidD_GetHidGuid(&id);

	/*The SetupDiGetClassDevs function returns a handle to a device information set that 
	  contains requested device information elements for a local computer.*/
	HDEVINFO info = SetupDiGetClassDevs(&id, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
	if(info == INVALID_HANDLE_VALUE){
		return false;
	}
	else{
		BOOL hasnext = false;
		DWORD MemberIndex = 0;
		SP_DEVICE_INTERFACE_DATA devInterfaceData;
		do{
			memset(&devInterfaceData, 0, sizeof(SP_DEVICE_INTERFACE_DATA));
			devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

			/*The SetupDiEnumDeviceInterfaces function enumerates the device interfaces that
			  are contained in a device information set.*/
			hasnext = SetupDiEnumDeviceInterfaces(info, NULL, &id, MemberIndex++, &devInterfaceData);
			DWORD structSize = 0;

			/*
			The SetupDiGetDeviceInterfaceDetail function returns details about a device interface.
			Using this function to get details about an interface is typically a two-step process:
				- Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a NULL 
				  DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero, and
				  a valid RequiredSize variable. In response to such a call, this function returns
				  the required buffer size at RequiredSize and fails with GetLastError returning 
				  ERROR_INSUFFICIENT_BUFFER.
				- Allocate an appropriately sized buffer and call the function again to get the interface details.
			*/
			if((!SetupDiGetDeviceInterfaceDetail(info, &devInterfaceData, NULL, 0, &structSize, NULL)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)){
				if(structSize > 0){
					SP_DEVICE_INTERFACE_DETAIL_DATA *interfaceData = (SP_DEVICE_INTERFACE_DETAIL_DATA*) malloc(structSize);
					interfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
					if(SetupDiGetDeviceInterfaceDetail(info, &devInterfaceData, interfaceData, structSize, NULL, NULL)){
						if(interfaceData->DevicePath != NULL){
							HANDLE mouseHandle;

							//opening mouse handle
							if((mouseHandle = CreateFile(interfaceData->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
								NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL)) != INVALID_HANDLE_VALUE){
									HIDD_ATTRIBUTES attr;
									memset(&attr, 0, sizeof(HIDD_ATTRIBUTES));
									attr.Size = sizeof(HIDD_ATTRIBUTES);

									/*The HidD_GetAttributes routine returns the attributes of a specified 
									  top-level collection.
									*/
									if(HidD_GetAttributes(mouseHandle, &attr)){
										if((attr.VendorID == MY_VID) && (attr.ProductID == MY_PID)){
											if(interfaceData != NULL)
												free(interfaceData);
											SetupDiDestroyDeviceInfoList(info);
											return true;
										}
										else{
											CloseHandle(mouseHandle);
											if(interfaceData != NULL)
												free(interfaceData);
											continue;
										}
									}
									else{
										CloseHandle(mouseHandle);
										if(interfaceData != NULL)
											free(interfaceData);
										continue;
									}
							}  
							else{
								if(interfaceData != NULL)
									free(interfaceData);
								continue;
							}
						}
						else{
							if(interfaceData != NULL)
								free(interfaceData);
							continue;
						}
					}
					else{
						if(interfaceData != NULL)
							free(interfaceData);
						continue;
					}
				}
				else{
					continue;
				}
			}
			else{
				continue;
			}
		}while(hasnext);
		SetupDiDestroyDeviceInfoList(info);
		return false;
	}
}

